package com.eudon.genius.api.core.parser.component;

import com.eudon.genius.api.core.dto.ApiInfo;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.expr.*;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * Spring注解解析器
 * 负责解析Spring Web相关注解，提取URL路径、HTTP方法等信息
 *
 * @author eudon
 * @since 2025/9/25
 */
@Slf4j
public class AnnotationParser {

    /**
     * HTTP方法映射注解
     */
    private static final Map<String, String> HTTP_METHOD_ANNOTATIONS;

    static {
        Map<String, String> map = new HashMap<>();
        map.put("GetMapping", "GET");
        map.put("PostMapping", "POST");
        map.put("PutMapping", "PUT");
        map.put("DeleteMapping", "DELETE");
        map.put("PatchMapping", "PATCH");
        HTTP_METHOD_ANNOTATIONS = Collections.unmodifiableMap(map);
    }

    /**
     * 参数注解映射
     */
    private static final Map<String, ApiInfo.ParameterLocation> PARAMETER_ANNOTATIONS;

    static {
        Map<String, ApiInfo.ParameterLocation> paramMap = new HashMap<>();
        paramMap.put("RequestParam", ApiInfo.ParameterLocation.QUERY);
        paramMap.put("PathVariable", ApiInfo.ParameterLocation.PATH);
        paramMap.put("RequestBody", ApiInfo.ParameterLocation.BODY);
        paramMap.put("RequestHeader", ApiInfo.ParameterLocation.HEADER);
        paramMap.put("CookieValue", ApiInfo.ParameterLocation.COOKIE);
        PARAMETER_ANNOTATIONS = Collections.unmodifiableMap(paramMap);
    }

    /**
     * 解析类级别的@RequestMapping注解
     *
     * @param classDeclaration 类声明
     * @return 类级别的URL路径
     */
    public String parseClassRequestMapping(ClassOrInterfaceDeclaration classDeclaration) {
        return classDeclaration.getAnnotations().stream()
                .filter(this::isRequestMappingAnnotation)
                .findFirst()
                .map(this::extractUrlFromAnnotation)
                .orElse("");
    }

    /**
     * 解析方法级别的映射注解
     *
     * @param methodDeclaration 方法声明
     * @return 方法映射信息
     */
    public MethodMappingInfo parseMethodMapping(MethodDeclaration methodDeclaration) {
        MethodMappingInfo mappingInfo = new MethodMappingInfo();

        // 查找HTTP方法注解
        Optional<AnnotationExpr> httpMethodAnnotation = methodDeclaration.getAnnotations().stream()
                .filter(this::isHttpMethodAnnotation)
                .findFirst();

        if (httpMethodAnnotation.isPresent()) {
            AnnotationExpr annotation = httpMethodAnnotation.get();
            String annotationName = getSimpleAnnotationName(annotation.getNameAsString());

            // 设置HTTP方法
            mappingInfo.setHttpMethod(HTTP_METHOD_ANNOTATIONS.getOrDefault(annotationName, "GET"));

            // 提取URL路径
            mappingInfo.setUrl(extractUrlFromAnnotation(annotation));
        } else {
            // 查找@RequestMapping注解
            Optional<AnnotationExpr> requestMappingAnnotation = methodDeclaration.getAnnotations().stream()
                    .filter(this::isRequestMappingAnnotation)
                    .findFirst();

            if (requestMappingAnnotation.isPresent()) {
                AnnotationExpr annotation = requestMappingAnnotation.get();
                mappingInfo.setUrl(extractUrlFromAnnotation(annotation));
                mappingInfo.setHttpMethod(extractHttpMethodFromRequestMapping(annotation));
            } else return null;
        }

        return mappingInfo;
    }

    /**
     * 解析参数注解
     *
     * @param parameter 参数
     * @return 参数注解信息
     */
    public ParameterAnnotationInfo parseParameterAnnotations(Parameter parameter) {
        ParameterAnnotationInfo annotationInfo = new ParameterAnnotationInfo();

        // 默认为查询参数
        annotationInfo.setLocation(ApiInfo.ParameterLocation.QUERY);
        annotationInfo.setRequired(false);
        annotationInfo.setNullable(true);

        for (AnnotationExpr annotation : parameter.getAnnotations()) {
            String annotationName = getSimpleAnnotationName(annotation.getNameAsString());

            // 解析参数位置注解
            if (PARAMETER_ANNOTATIONS.containsKey(annotationName)) {
                annotationInfo.setLocation(PARAMETER_ANNOTATIONS.get(annotationName));

                // 提取注解属性
                if (annotation instanceof SingleMemberAnnotationExpr) {
                    SingleMemberAnnotationExpr singleMember = (SingleMemberAnnotationExpr) annotation;
                    String value = extractStringValue(singleMember.getMemberValue());
                    if (!value.isEmpty()) {
                        annotationInfo.setName(value);
                    }
                } else if (annotation instanceof NormalAnnotationExpr) {
                    NormalAnnotationExpr normalAnnotation = (NormalAnnotationExpr) annotation;

                    // 提取value属性
                    normalAnnotation.getPairs().stream()
                            .filter(pair -> "value".equals(pair.getNameAsString()) || "name".equals(pair.getNameAsString()))
                            .findFirst()
                            .ifPresent(pair -> {
                                String value = extractStringValue(pair.getValue());
                                if (!value.isEmpty()) {
                                    annotationInfo.setName(value);
                                }
                            });

                    // 提取required属性
                    normalAnnotation.getPairs().stream()
                            .filter(pair -> "required".equals(pair.getNameAsString()))
                            .findFirst()
                            .ifPresent(pair -> {
                                if (pair.getValue() instanceof BooleanLiteralExpr) {
                                    boolean required = ((BooleanLiteralExpr) pair.getValue()).getValue();
                                    annotationInfo.setRequired(required);
                                    annotationInfo.setNullable(!required);
                                }
                            });

                    // 提取defaultValue属性
                    normalAnnotation.getPairs().stream()
                            .filter(pair -> "defaultValue".equals(pair.getNameAsString()))
                            .findFirst()
                            .ifPresent(pair -> {
                                String defaultValue = extractStringValue(pair.getValue());
                                annotationInfo.setDefaultValue(defaultValue);
                            });
                }
            }

            // 解析验证注解
            if ("NotNull".equals(annotationName) || "NonNull".equals(annotationName)) {
                annotationInfo.setNullable(false);
                annotationInfo.setRequired(true);
            } else if ("NotEmpty".equals(annotationName) || "NotBlank".equals(annotationName)) {
                annotationInfo.setNullable(false);
                annotationInfo.setRequired(true);
            }
        }

        // 如果没有指定名称，使用参数名
        if (annotationInfo.getName() == null || annotationInfo.getName().isEmpty()) {
            annotationInfo.setName(parameter.getNameAsString());
        }

        return annotationInfo;
    }

    /**
     * 判断是否为RequestMapping注解
     */
    private boolean isRequestMappingAnnotation(AnnotationExpr annotation) {
        String name = getSimpleAnnotationName(annotation.getNameAsString());
        return "RequestMapping".equals(name);
    }

    /**
     * 判断是否为HTTP方法注解
     */
    private boolean isHttpMethodAnnotation(AnnotationExpr annotation) {
        String name = getSimpleAnnotationName(annotation.getNameAsString());
        return HTTP_METHOD_ANNOTATIONS.containsKey(name);
    }

    /**
     * 从注解中提取URL路径
     */
    private String extractUrlFromAnnotation(AnnotationExpr annotation) {
        if (annotation instanceof SingleMemberAnnotationExpr) {
            SingleMemberAnnotationExpr singleMember = (SingleMemberAnnotationExpr) annotation;
            return extractStringValue(singleMember.getMemberValue());
        } else if (annotation instanceof NormalAnnotationExpr) {
            NormalAnnotationExpr normalAnnotation = (NormalAnnotationExpr) annotation;
            return normalAnnotation.getPairs().stream()
                    .filter(pair -> "value".equals(pair.getNameAsString()) || "path".equals(pair.getNameAsString()))
                    .findFirst()
                    .map(pair -> extractStringValue(pair.getValue()))
                    .orElse("");
        }
        return "";
    }

    /**
     * 从@RequestMapping注解中提取HTTP方法
     */
    private String extractHttpMethodFromRequestMapping(AnnotationExpr annotation) {
        if (annotation instanceof NormalAnnotationExpr) {
            NormalAnnotationExpr normalAnnotation = (NormalAnnotationExpr) annotation;
            return normalAnnotation.getPairs().stream()
                    .filter(pair -> "method".equals(pair.getNameAsString()))
                    .findFirst()
                    .map(pair -> {
                        String methodValue = pair.getValue().toString();
                        if (methodValue.contains("GET")) return "GET";
                        if (methodValue.contains("POST")) return "POST";
                        if (methodValue.contains("PUT")) return "PUT";
                        if (methodValue.contains("DELETE")) return "DELETE";
                        if (methodValue.contains("PATCH")) return "PATCH";
                        return "GET";
                    })
                    .orElse("GET");
        }
        return "GET";
    }

    /**
     * 提取字符串值
     */
    private String extractStringValue(Expression expression) {
        if (expression instanceof StringLiteralExpr) {
            return ((StringLiteralExpr) expression).asString();
        } else if (expression instanceof ArrayInitializerExpr) {
            ArrayInitializerExpr arrayExpr = (ArrayInitializerExpr) expression;
            return arrayExpr.getValues().stream()
                    .filter(expr -> expr instanceof StringLiteralExpr)
                    .map(expr -> ((StringLiteralExpr) expr).asString())
                    .collect(Collectors.joining(","));
        }
        return expression.toString().replaceAll("\"|", "");
    }

    /**
     * 获取简单注解名称
     */
    private String getSimpleAnnotationName(String fullName) {
        int lastDot = fullName.lastIndexOf('.');
        return lastDot >= 0 ? fullName.substring(lastDot + 1) : fullName;
    }

    /**
     * 方法映射信息
     */
    @Setter
    @Getter
    public static class MethodMappingInfo {
        private String url = "";
        private String httpMethod = "GET";

    }

    /**
     * 参数注解信息
     */
    @Getter
    @Setter
    public static class ParameterAnnotationInfo {
        private String name;
        private ApiInfo.ParameterLocation location;
        private boolean required;
        private boolean nullable;
        private String defaultValue;

    }
}